﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
#if !NETFX_CORE
using System.IO.IsolatedStorage;
#endif

namespace NCache
{
    public class StorageHelper
    {
#if NETFX_CORE
        private static ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
#else
        private static System.IO.IsolatedStorage.IsolatedStorageSettings settings = System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings;
#endif

        #region SyncLockWithStorageFolder

        private static object _localFolderLock = new object();

        private static StorageFolder _localFolder = null;
        private static StorageFolder LocalFolder
        {
            get
            {
                lock (_localFolderLock)
                {
                    if (_localFolder == null)
                    {
                        _localFolder = ApplicationData.Current.LocalFolder;
                    }
                    return _localFolder;
                }
            }
        }

        #endregion

        #region SettingOperation

        //保存设置  
        //替换设置
        public static void SaveToSetting(string key, object value)
        {
#if NETFX_CORE
            settings.Values[key] = value;
            
#else
            settings[key] = value;
            settings.Save();
#endif
        }

        //删除设置
        public static void DeleteSetting(string key)
        {
#if NETFX_CORE
            settings.Values.Remove(key);
            
#else
            settings.Remove(key);
            settings.Save();
#endif
        }
      
        //获取设置
        public static T GetSettings<T>(string key)
        {
             object value = null;

#if NETFX_CORE
             if (settings.Values.ContainsKey(key))
             {
                 value = settings.Values[key];
             }
#else
            if (settings.Contains(key))
            {
                value = settings[key];
            }
#endif

            if (value == null)
            {
                return default(T);
            }
            return (T)value;
        }

        #endregion

        #region FileOperation

        //保存文件
        public static async void SaveFileAsync(byte[] byteArray, string fileName, string folderName)
        {
            try
            {
                //TODO 这个地方需要在队里去重复，并且在这里判断是否有人在用，即文件已经存在，如果存在进行相应的处理
                //Debug.WriteLine("begin save file :" + fileName);
                StorageFolder folder = await GetFolderAsync(folderName).ConfigureAwait(false);
                var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
                MemoryStream saveData = new MemoryStream(byteArray);
                if (saveData.Length > 0)
                {
                    // Get an output stream for the SessionState file and write the state asynchronously
                    using (var fileStream = await file.OpenStreamForWriteAsync().ConfigureAwait(false))
                    {
                        saveData.Seek(0, SeekOrigin.Begin);
                        await saveData.CopyToAsync(fileStream).ConfigureAwait(false);
                        await fileStream.FlushAsync().ConfigureAwait(false);
                    }
                }
            }
            catch(Exception ex)
            {
                Debug.WriteLine("save file error: folderName:" + folderName + "fileName:" + fileName + "error msg: " + ex.Message.ToString());
            }
        }

        //读取文件流
        public static async Task<byte[]> GetFileStreamAysnc(string folderName, string fileName)
        {
            byte[] data = null;
            try
            {
                //Debug.WriteLine("begin get file:" + fileName);
                StorageFile file = await GetFileAsync(folderName, fileName).ConfigureAwait(false);
                IRandomAccessStream accessStream = await file.OpenReadAsync();
                using (Stream stream = accessStream.AsStreamForRead((int)accessStream.Size))
                {
                    data = new byte[stream.Length];
                    await stream.ReadAsync(data, 0, (int)stream.Length).ConfigureAwait(false);
                }
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine("ImageCache - GetFileStreamAysnc() - Has Error: folderName" + folderName + "fileName" + fileName + "error msg: " + ex.Message.ToString());
            }
            return data;
        }

        //读取文件
        public static async Task<StorageFile> GetFileAsync(string folderName, string fileName)
        {
            try
            {
                StorageFolder folder = await GetFolderAsync(folderName).ConfigureAwait(false);
                StorageFile file = await folder.GetFileAsync(fileName);
                return file;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        //删除文件
        public static void DeleteFile(string folderName, string fileName)
        {
            Task.Run(async () =>
                {
                    StorageFile file = await GetFileAsync(folderName, fileName).ConfigureAwait(false);
                    await file.DeleteAsync();
                });
        }

        //获取文件夹
        public static async Task<StorageFolder> GetFolderAsync(string folderName)
        {
            if (string.IsNullOrEmpty(folderName))
            {
                throw new ArgumentNullException("folderName is null");
            }
            StorageFolder folder = LocalFolder;
            try
            {
                if (folderName.Contains("/"))
                {
                    string[] folderNameArray = folderName.Split('/');
                    for (int i = 0; i < folderNameArray.Length; i++)
                    {
                        string subFolderName = folderNameArray[i];
                        folder = await folder.CreateFolderAsync(subFolderName, CreationCollisionOption.OpenIfExists);
                    }
                }
                else
                {
                    folder = await folder.CreateFolderAsync(folderName, CreationCollisionOption.OpenIfExists);
                }
                return folder;
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine("GetFolderAsync Has Exception:" + ex.Message.ToString());
                
            }
            return folder;
        }

        //包含文件
        public static async Task<bool> Exists(string folderName, string fileName)
        {
            //This looks nicer, but gave a COM errors in some situations
            //TODO: Check again in final release of Windows 8 (or 9, or 10) this way will cause memory leak
            //StorageFolder folder = await GetFolderAsync(folderName).ConfigureAwait(false);
            //return (await folder.GetFilesAsync()).Where(file => file.Name == fileName).Any();
#if NETFX_CORE
             try
            {
                StorageFolder folder = await GetFolderAsync(folderName).ConfigureAwait(false);
                await folder.GetFileAsync(fileName);
                return true;
            }
            catch
            {
                return false;
            }
#else
            //the last way can be used,but always throw FileNotFoundException,
            //it cause diffcult to debug the code,
            //so use the isoloatedstoragefile to check the file exists
            IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
            return store.FileExists(folderName + "/" + fileName);
#endif

        }

        //清楚文件夹下的所有文件
        public static Task ClearAll(string folerName)
        {
            return Task.Run(async () =>
            {
                var folder = await GetFolderAsync(folerName).ConfigureAwait(false);
                try
                {
                    await folder.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask().ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("exception :" + ex.Message.ToString());
                }
            });
        }

        #endregion

        #region PathUtils

        //根据路径获取文件名称
        private static string GetFileName(string filePath)
        {
            string fileName = filePath.Substring(filePath.LastIndexOf("/") + 1);
            return fileName;
        }

        //根据路径后去所有文件夹的名称
        private static List<string> GetFoldersName(string filePath)
        {
            try
            {
                string folderPath = filePath.Substring(1, filePath.LastIndexOf("/") - 1);
                string[] folder = folderPath.Split('/');
                List<string> foldersName = folder.ToList();
                return foldersName;
            }
            catch (Exception)
            {
                throw new Exception("GetFoldersName is error !");
            }
        }

        #endregion
    }
}
